package com.lmz.project.redis.arithmetic;

import java.math.BigDecimal;
import java.util.Arrays;

/**
 * 基尼系数实验
 */
public class Gini {
    /**
     * 实验：假设每个人初始财富有100元，每一轮随机给一个人一块钱，如果这一轮没有钱，则不需要给钱，可以接收，实验多少轮，看基尼系数的值
     */
    public static void main(String[] args) {
        int t = 1000000; //轮数
        int n = 100; //人数
        int[] wealthArr = new int[n];
        Arrays.fill(wealthArr, 100);
        System.out.println("初始数据");
        System.out.println(Arrays.toString(wealthArr));
        double experiment = experiment(wealthArr, t, n); //开始实验
        Arrays.sort(wealthArr);
        System.out.println(Arrays.toString(wealthArr));
//        System.out.println(experiment);
        BigDecimal bigDecimal = new BigDecimal(String.valueOf(experiment));//0.0004
        System.out.println(bigDecimal);

    }


    public static double experiment(int[] wealthArr, int t, int n) {

        for (int j = 0; j < t; j++) {
            //首先认为所有人都没有钱
            boolean[] isHaveWealth = new boolean[n];
            //初始化每个人是否有财富
            for (int i = 0; i < n; i++) {
                if (wealthArr[i] > 0) {
                    isHaveWealth[i] = true;
                }
            }
            for (int i = 0; i < n; i++) {
                if (isHaveWealth[i]) {
                    int other = i; //首先认为给的目标是自己
                    do {
                        other = (int) (Math.random() * n);
                    } while (i == other);
                    wealthArr[i]--;
                    wealthArr[other]++;
                }
            }
        }

        return calculateGini(n, wealthArr);
    }


    /**
     * 计算基尼系数
     *
     * @param n         总人数
     * @param wealthArr 每个人拥有的财富数组
     * @return
     */
    public static double calculateGini(int n, int[] wealthArr) {
        double countWealth = 0;
        double countDifferences = 0;
        //基尼系数计算公式 ： 差值总和 / （2*人数*财富总和）
        for (int i = 0; i < n; i++) {
            countWealth += wealthArr[i];
            for (int j = 0; j < n; j++) {
                countDifferences += Math.abs(wealthArr[i] - wealthArr[j]);
            }
        }
        return countDifferences / (2 * n * countWealth);
    }
}
